package com.rabbit.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rabbit.constant.ResultCodeEnum;
import com.rabbit.db.entity.Config;
import com.rabbit.exception.BusinessException;
import com.rabbit.mapper.ConfigMapper;
import com.rabbit.redis.constant.RedisKeyConstant;
import com.rabbit.redis.service.RedisService;
import com.rabbit.service.ConfigService;
import com.rabbit.vo.req.ConfigReq;
import com.rabbit.vo.res.ConfigRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <h1>参数管理业务实现类</h1>
 *
 * @author zjw
 * @date 2022/1/21 14:45
 */
@Service
@Slf4j
public class ConfigServiceImpl implements ConfigService {

    @Resource
    private ConfigMapper configMapper;

    @Resource
    private RedisService redisService;

    @Override
    public PageInfo<ConfigRes> queryConfigList(ConfigReq configReq) {
        Config config = Config.builder().build();
        BeanUtils.copyProperties(configReq, config);
        return PageHelper.startPage(configReq.getPage(), configReq.getLimit())
                .doSelectPageInfo(() -> configMapper.queryConfigList(config));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteConfig(ConfigReq configReq) {
        configMapper.deleteByPrimaryKey(configReq.getConfigId());
        refreshCache();
    }

    @Override
    public ConfigRes queryConfigById(Long configId) {
        ConfigRes configRes = ConfigRes.builder().build();
        Config config = configMapper.selectByPrimaryKey(configId);
        BeanUtils.copyProperties(config, configRes);
        return configRes;
    }

    @Override
    public void checkUnique(ConfigReq configReq, int operType) throws BusinessException {
        // 1. 参数名称唯一
        Example configNameExample = new Example(Config.class);
        Example.Criteria configNameCriteria = configNameExample.createCriteria();
        configNameCriteria.andEqualTo("configName", configReq.getConfigName());
        if (operType > 1) {
            configNameCriteria.andNotEqualTo("configId", configReq.getConfigId());
        }
        if (configMapper.selectCountByExample(configNameExample) > 0) {
            throw new BusinessException(ResultCodeEnum.CONFIG_NAME_EXISTS_ERROR);
        }
        // 2. 参数Key唯一
        Example configKeyExample = new Example(Config.class);
        Example.Criteria configKeyCriteria = configKeyExample.createCriteria();
        configKeyCriteria.andEqualTo("configKey", configReq.getConfigKey());
        if (operType > 1) {
            configKeyCriteria.andNotEqualTo("configId", configReq.getConfigId());
        }
        if (configMapper.selectCountByExample(configKeyExample) > 0) {
            throw new BusinessException(ResultCodeEnum.CONFIG_KEY_EXISTS_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addConfig(ConfigReq configReq) {
        Config config = Config.builder().build();
        BeanUtils.copyProperties(configReq, config);
        config.setCreateBy(configReq.getOperatorUserName());
        configMapper.insertSelective(config);
        refreshCache();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateConfig(ConfigReq configReq) {
        Config config = Config.builder().build();
        BeanUtils.copyProperties(configReq, config);
        config.setUpdateBy(configReq.getOperatorUserName());
        configMapper.updateByPrimaryKeySelective(config);
        refreshCache();
    }

    @Override
    public void refreshCache() {
        ConfigReq configReq = ConfigReq.builder().build();
        configReq.setPage(1);
        configReq.setLimit(999);
        List<ConfigRes> configs = queryConfigList(configReq).getList();
        Map<String, String> configMap = configs.stream().collect(Collectors.toMap(ConfigRes::getConfigKey, ConfigRes::getConfigValue));
        redisService.hPutAll(RedisKeyConstant.SYS_CONFIG, configMap);
        log.info("*****刷新参数缓存成功*****");
    }
}
